home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#27 (Dec 87)
/
Forth Hypercard cmd
/
XCMD defs.edit
next >
Wrap
Text File
|
1987-11-13
|
9KB
|
289 lines
( *** Hypercard external commands. J.L. October 1987 *** )
ONLY FORTH ALSO ASSEMBLER ALSO MAC
4ascii XFCN CONSTANT "xfcn
4ascii XCMD CONSTANT "xcmd
$9DE CONSTANT WMgrPort
\ structure of a Hypercard parameter block
0 CONSTANT paramCount \ INTEGER; the number of arguments
2 CONSTANT params \ ARRAY[1..16] OF Handle; the arguments
66 CONSTANT returnValue \ Handle; the result of this XCMD
70 CONSTANT passFlag \ BOOLEAN; pass the message on?
72 CONSTANT entryPoint \ ProcPtr; call back to HyperCard
76 CONSTANT request \ INTEGER; what you want to do
78 CONSTANT result \ INTEGER; the answer it gives
80 CONSTANT inArgs \ ARRAY[1..8] OF LongInt;
\ args XCMD sends HyperCard
112 CONSTANT outArgs \ ARRAY[1..4] OF LongInt;
\ answer HyperCard sends back
\ result codes
0 CONSTANT xresSucc
1 CONSTANT xresFail
2 CONSTANT xresNotImp
\ request codes
1 CONSTANT xreqSendCardMessage
2 CONSTANT xreqEvalExpr
3 CONSTANT xreqStringLength
4 CONSTANT xreqStringMatch
5 CONSTANT xreqSendHCMessage
6 CONSTANT xreqZeroBytes
7 CONSTANT xreqPasToZero
8 CONSTANT xreqZeroToPas
9 CONSTANT xreqStrToLong
10 CONSTANT xreqStrToNum
11 CONSTANT xreqStrToBool
12 CONSTANT xreqStrToExt
13 CONSTANT xreqLongToStr
14 CONSTANT xreqNumToStr
15 CONSTANT xreqNumToHex
16 CONSTANT xreqBoolToStr
17 CONSTANT xreqExtToStr
18 CONSTANT xreqGetGlobal
19 CONSTANT xreqSetGlobal
20 CONSTANT xreqGetFieldByName
21 CONSTANT xreqGetFieldByNum
22 CONSTANT xreqGetFieldByID
23 CONSTANT xreqSetFieldByName
24 CONSTANT xreqSetFieldByNum
25 CONSTANT xreqSetFieldByID
26 CONSTANT xreqStringEqual
27 CONSTANT xreqReturnToPas
28 CONSTANT xreqScanToReturn
39 CONSTANT xreqScanToZero \ was supposed to be 29. Oops!
( **** Pascal definitions for the callable Hypercard routines follow:
PROCEDURE SendCardMessage(msg: Str255);
{ Send a HyperCard message (a command with arguments) to the current card. }
FUNCTION EvalExpr(expr: Str255): Handle;
{ Evaluate a HyperCard expression and return the answer. The answer is
a handle to a zero-terminated string. }
FUNCTION StringLength(strPtr: Ptr): LongInt;
{ Count the characters from where strPtr points until the next zero byte.
Does not count the zero itself. strPtr must be a zero-terminated string. }
FUNCTION StringMatch(pattern: Str255; target: Ptr): Ptr;
{ Perform case-insensitive match looking for pattern anywhere in
target, returning a pointer to first character of the first match,
in target or NIL if no match found. pattern is a Pascal string,
and target is a zero-terminated string. }
PROCEDURE ZeroBytes(dstPtr: Ptr; longCount: LongInt);
{ Write zeros into memory starting at destPtr and going for longCount
number of bytes. }
FUNCTION PasToZero(str: Str255): Handle;
{ Convert a Pascal string to a zero-terminated string. Returns a handle
to a new zero-terminated string. The caller must dispose the handle.
You'll need to do this for any result or argument you send from
your XCMD to HyperTalk. }
PROCEDURE ZeroToPas(zeroStr: Ptr; VAR pasStr: Str255);
{ Fill the Pascal string with the contents of the zero-terminated
string. You create the Pascal string and pass it in as a VAR
parameter. Useful for converting the arguments of any XCMD to
Pascal strings.}
FUNCTION StrToLong(str: Str31): LongInt;
{ Convert a string of ASCII decimal digits to an unsigned long integer. }
FUNCTION StrToNum(str: Str31): LongInt;
{ Convert a string of ASCII decimal digits to a signed long integer.
Negative sign is allowed. }
FUNCTION StrToBool(str: Str31): BOOLEAN;
{ Convert the Pascal strings 'true' and 'false' to booleans. }
FUNCTION StrToExt(str: Str31): Extended;
{ Convert a string of ASCII decimal digits to an extended long integer. }
VAR x: Extended;
FUNCTION LongToStr(posNum: LongInt): Str31;
{ Convert an unsigned long integer to a Pascal string. }
FUNCTION NumToStr(num: LongInt): Str31;
{ Convert a signed long integer to a Pascal string. }
FUNCTION NumToHex(num: LongInt; nDigits: INTEGER): Str31;
{ Convert an unsigned long integer to a hexadecimal number and put it
into a Pascal string. }
FUNCTION BoolToStr(bool: BOOLEAN): Str31;
{ Convert a boolean to 'true' or 'false'. }
VAR str: Str31;
FUNCTION ExtToStr(num: Extended): Str31;
{ Convert an extended long integer to decimal digits in a string. }
FUNCTION GetGlobal(globName: Str255): Handle;
{ Return a handle to a zero-terminated string containing the value of
the specified HyperTalk global variable. }
PROCEDURE SetGlobal(globName: Str255; globValue: Handle);
{ Set the value of the specified HyperTalk global variable to be
the zero-terminated string in globValue. The contents of the
Handle are copied, so you must still dispose it afterwards. }
FUNCTION GetFieldByName(cardFieldFlag: BOOLEAN; fieldName: Str255): Handle;
{ Return a handle to a zero-terminated string containing the value of
field fieldName on the current card. You must dispose the handle. }
FUNCTION GetFieldByNum(cardFieldFlag: BOOLEAN; fieldNum: INTEGER): Handle;
{ Return a handle to a zero-terminated string containing the value of
field fieldNum on the current card. You must dispose the handle. }
FUNCTION GetFieldByID(cardFieldFlag: BOOLEAN; fieldID: INTEGER): Handle;
{ Return a handle to a zero-terminated string containing the value of
the field whise ID is fieldID. You must dispose the handle. }
PROCEDURE SetFieldByName(cardFieldFlag: BOOLEAN; fieldName: Str255; fieldVal: Handle);
{ Set the value of field fieldName to be the zero-terminated string
in fieldVal. The contents of the Handle are copied, so you must
still dispose it afterwards. }
PROCEDURE SetFieldByNum(cardFieldFlag: BOOLEAN; fieldNum: INTEGER; fieldVal: Handle);
{ Set the value of field fieldNum to be the zero-terminated string
in fieldVal. The contents of the Handle are copied, so you must
still dispose it afterwards. }
PROCEDURE SetFieldByID(cardFieldFlag: BOOLEAN; fieldID: INTEGER; fieldVal: Handle);
{ Set the value of the field whose ID is fieldID to be the zero-
terminated string in fieldVal. The contents of the Handle are
copied, so you must still dispose it afterwards. }
FUNCTION StringEqual(str1,str2: Str255): BOOLEAN;
{ Return true if the two strings have the same characters.
Case insensitive compare of the strings. }
PROCEDURE ReturnToPas(zeroStr: Ptr; VAR pasStr: Str255);
{ zeroStr points into a zero-terminated string. Collect the
characters from there to the next carriage Return and return
them in the Pascal string pasStr. If a Return is not found,
collect chars until the end of the string. }
PROCEDURE ScanToReturn(VAR scanPtr: Ptr);
{ Move the pointer scanPtr along a zero-terminated
string until it points at a Return character
or a zero byte. }
PROCEDURE ScanToZero(VAR scanPtr: Ptr);
{ Move the pointer scanPtr along a zero-terminated
string until it points at a zero byte. }
**** End of Pascal definitions )
\ **** Hypercard glue macros
CODE HC.prelude
LINK A6,#-512 ( 512 bytes of local Forth stack )
MOVEM.L A0-A5/D0-D7,-(A7) ( save registers )
MOVE.L A6,A3 ( setup local loop return stack )
SUBA.L #256,A3 ( in the low 256 local stack bytes )
MOVE.L 8(A6),D0 ( pointer to parameter block )
MOVE.L D0,-(A6)
RTS \ just to indicate the MACHro stops here
END-CODE MACH
CODE HC.epilogue
MOVEM.L (A7)+,A0-A5/D0-D7 ( restore registers )
UNLK A6
MOVE.L (A7)+,A0 ( return address )
ADD.W #4,A7 ( pop off 4 bytes of parameters )
JMP (A0)
RTS
END-CODE MACH
( ------------------- )
header flashy.start
JMP flashy.start ( to be filled later )
header doneString
DC.B 'Done'
DC.B 0
header errorString
DC.B 'Error'
DC.B 0
header PascalString 255 allot
CODE callJSR
MOVE.L (A6)+,-(A7)
RTS
END-CODE
: ZeroToPas { HCPars CStr PStr | -- }
CStr HCPars inArgs + !
PStr HCPars inArgs + 4 + !
xreqZeroToPas HCPars request + w!
HCPars entryPoint + @ callJSR ( call Hypercard here )
;
: StrToNum { HCPars Str | -- result }
Str HCPars inArgs + !
xreqStrToNum HCPars request + w!
HCPars entryPoint + @ callJSR
HCPars outArgs + @
;
: flashy { HCpars | hP1 screen times -- }
HCPars params + @ -> hP1
hP1 (call) HLock drop \ yes, I know I'm paranoid about this
HCPars hP1 @ ['] PascalString ZeroToPas
hP1 (call) HUnLock drop
HCPars ['] PascalString StrToNum -> times
times 0> IF
WMgrPort @ -> screen
times 0 DO
screen portRect + dup
(call) InvertRect (call) InvertRect
LOOP
['] doneString 5 (call) PtrToHand drop
HCpars returnValue + !
ELSE
['] errorString 6 (call) PtrToHand drop
HCpars returnValue + !
THEN
;
: flashy.glue
HC.prelude flashy HC.epilogue ;
header flashy.end
' flashy.glue ' flashy.start 2+ - ' flashy.start 2+ w!
( *** making the XCMD resource *** )
: $create-res call CreateResFile call ResError L_ext ;
: $open-res { addr | refNum -- result }
addr call openresfile -> refNum
call ResError L_ext
dup not IF drop refNum THEN
;
: $close-res call CloseResFile call ResError L_ext ;
: make-xcmd { | refNum -- }
" xcmd.res" dup $create-res
abort" You have to delete the old 'xcmd.res' file first."
$open-res dup -> refNum call UseResFile
['] flashy.start ['] flashy.end over -
call PtrToHand drop ( result code )
"xcmd 2000 " flashy" call AddResource
refNum $close-res drop ( result code )
;